package ae.pcfc.cldos.online.common.facade.provider;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.ws.client.WebServiceIOException;
import org.springframework.ws.soap.client.SoapFaultClientException;

import ae.pcfc.cldos.online.common.clddb.domain.FnpDefaultParams;
import ae.pcfc.cldos.online.common.clddb.domain.FnpParamMapper;
import ae.pcfc.cldos.online.common.clddb.domain.FnpServiceMaster;
import ae.pcfc.cldos.online.common.clddb.domain.manager.FnpDefaultParamsDOM;
import ae.pcfc.cldos.online.common.clddb.domain.manager.FnpGSDOM;
import ae.pcfc.cldos.online.common.clddb.domain.manager.FnpParamMapperDOM;
import ae.pcfc.cldos.online.common.etksdb.domain.Client;
import ae.pcfc.cldos.online.common.etksdb.domain.User;
import ae.pcfc.cldos.online.common.etksdb.domain.manager.UserDomainObjectManager;
import ae.pcfc.cldos.online.common.exception.BadAppException;
import ae.pcfc.cldos.online.common.exception.GSAppException;
import ae.pcfc.cldos.online.common.exception.NoSuchCompanyException;
import ae.pcfc.cldos.online.common.facade.BaseFacade;
import ae.pcfc.cldos.online.common.facade.FnpGSFacade;
import ae.pcfc.cldos.online.common.manager.FNPManager;
import ae.pcfc.cldos.online.common.manager.GsInfoManager;
import ae.pcfc.cldos.online.common.tscdb.domain.TTscClientCompany;
import ae.pcfc.cldos.online.common.vo.FnpDefaultParamsVO;
import ae.pcfc.cldos.online.common.vo.FnpParamMapperVO;
import ae.pcfc.cldos.online.common.vo.UserVO;
import ae.pcfc.cldos.online.common.vo.ep.peyment.PaymentAdviceRequestVO;
import ae.pcfc.cldos.online.common.vo.ep.peyment.PaymentAdviceResponseVO;
import ae.pcfc.cldos.online.fnp.ConstantsFNP;
import ae.pcfc.cldos.online.fnp.exception.FNPException;
import ae.pcfc.cldos.online.fnp.service.client.FinanceNPaymentFNP;
import ae.pcfc.cldos.online.fnp.service.client.vo.FNPAccountTypeVO;
import ae.pcfc.cldos.online.fnp.service.client.vo.FNPCatalogVO;
import ae.pcfc.cldos.online.fnp.service.client.vo.FNPParameterVO;
import ae.pcfc.cldos.online.fnp.service.client.vo.FNPPaymentAdviceReqVO;
import ae.pcfc.cldos.online.fnp.service.client.vo.FNPPaymentAdviceRspnsVO;
import ae.pcfc.cldos.online.fnp.service.client.vo.FNPPrepaidTransactionVO;
import ae.pcfc.cldos.online.fnp.service.client.vo.FNPServicePayResponseVO;
import ae.pcfc.cldos.online.gs.service.client.GovtSysGS;
import ae.pcfc.cldos.online.gs.service.client.vo.GSFinancialDataVO;

/**
 * 
 * @author akhader
 *
 */
public class FnpGSFacadeImpl extends BaseFacade implements FnpGSFacade {
	
	private UserDomainObjectManager userDOM;
	private ae.pcfc.cldos.online.common.etksdb.domain.manager.ClientDOM clientDOM;
	private ae.pcfc.cldos.online.common.tscdb.domain.manager.TTscClientCompanyDOM tTscClientCompanyDOM;
	private GovtSysGS govtSysGS;
	private FinanceNPaymentFNP financeNPaymentFNP;
	private FnpGSDOM FnpGSDOM;
	private FNPManager FNPManager;
	private FnpDefaultParamsDOM fnpDefaultParamsDOM;
	private FnpParamMapperDOM fnpParamMapperDOM;
	private GsInfoManager gsInfoManager;
	
	public void setGsInfoManager(GsInfoManager gsInfoManager) {
		this.gsInfoManager = gsInfoManager;
	}

	public FnpParamMapperDOM getFnpParamMapperDOM() {
		return fnpParamMapperDOM;
	}

	public void setFnpParamMapperDOM(FnpParamMapperDOM fnpParamMapperDOM) {
		this.fnpParamMapperDOM = fnpParamMapperDOM;
	}

	public FnpDefaultParamsDOM getFnpDefaultParamsDOM() {
		return fnpDefaultParamsDOM;
	}

	public void setFnpDefaultParamsDOM(FnpDefaultParamsDOM fnpDefaultParamsDOM) {
		this.fnpDefaultParamsDOM = fnpDefaultParamsDOM;
	}

	public void setUserDomainObjectManager(
			UserDomainObjectManager userDomainObjectManager) {
		this.userDOM = userDomainObjectManager;
	}

	public UserDomainObjectManager getUserDOM() {
		return userDOM;
	}

	public void setUserDOM(UserDomainObjectManager userDOM) {
		this.userDOM = userDOM;
	}

	public FNPManager getFNPManager() {
		return FNPManager;
	}

	public void setFNPManager(FNPManager fNPManager) {
		FNPManager = fNPManager;
	}

	public ae.pcfc.cldos.online.common.etksdb.domain.manager.ClientDOM getClientDOM() {
		return clientDOM;
	}

	public void setClientDOM(
			ae.pcfc.cldos.online.common.etksdb.domain.manager.ClientDOM clientDOM) {
		this.clientDOM = clientDOM;
	}

	public ae.pcfc.cldos.online.common.tscdb.domain.manager.TTscClientCompanyDOM gettTscClientCompanyDOM() {
		return tTscClientCompanyDOM;
	}

	public void settTscClientCompanyDOM(
			ae.pcfc.cldos.online.common.tscdb.domain.manager.TTscClientCompanyDOM tTscClientCompanyDOM) {
		this.tTscClientCompanyDOM = tTscClientCompanyDOM;
	}

	public GovtSysGS getGovtSysGS() {
		return govtSysGS;
	}

	public void setGovtSysGS(GovtSysGS govtSysGS) {
		this.govtSysGS = govtSysGS;
	}

	public FinanceNPaymentFNP getFinanceNPaymentFNP() {
		return financeNPaymentFNP;
	}

	public void setFinanceNPaymentFNP(FinanceNPaymentFNP financeNPaymentFNP) {
		this.financeNPaymentFNP = financeNPaymentFNP;
	}

	public FnpGSDOM getFnpGSDOM() {
		return FnpGSDOM;
	}

	public void setFnpGSDOM(FnpGSDOM fnpGSDOM) {
		FnpGSDOM = fnpGSDOM;
	}

	/* (non-Javadoc)
	 * @see ae.pcfc.cldos.online.common.facade.FnpFacade#findUserByUserName(java.lang.String)
	 */
	@Transactional
	public User findUserByUserName(String userName){
		return userDOM.findUserByUserName(userName);
	}
	/* (non-Javadoc)
	 * @see ae.pcfc.cldos.online.common.facade.FnpFacade#getClientById(java.lang.Long)
	 */
	@Transactional
	public Client getClientById(Long clientId){
		return clientDOM.getClientById(clientId);
	}
	/* (non-Javadoc)
	 * @see ae.pcfc.cldos.online.common.facade.FnpFacade#getCompanyByTrakheesId(java.lang.String)
	 */
	@Transactional
	public TTscClientCompany getCompanyByTrakheesId(String trakheesId){
		return tTscClientCompanyDOM.getCompanyByTrakheesId(trakheesId);
	}
	/**
	 * @param clientLicenseNumber
	 * @return
	 */
	public GSFinancialDataVO retreiveFinancialData(String clientLicenseNumber){
		return govtSysGS.retreiveFinancialData(clientLicenseNumber);
	}
	/**
	 * @return List<FNPCatalogVO>
	 * @throws FNPException
	 * @{@link Parameter} List<String> fnpServiceCodeList
	 */
	public List<FNPCatalogVO> retreiveFNPCatalog(List<String> fnpServiceCodeList){
		return financeNPaymentFNP.retreiveFNPCatalog(fnpServiceCodeList);
	}
	/**
	 * @param serviceIdList
	 * @return
	 */
	public List<FNPParameterVO> retreiveAllFNPParameters(List<String> serviceIdList){
		List<FNPParameterVO> fnpParameters = financeNPaymentFNP.retreiveFNPParameters(serviceIdList);
		return fnpParameters;
	}
	/**
	 * @param List<String> serviceIdList
	 * @return List<FNPParameterVO>
	 * @throws FNPException
	 */
	@Transactional
	public List<FNPParameterVO> retreiveFNPParameters(List<String> serviceIdList){
		List<FNPParameterVO> fnpParameters = null;
		try{
			fnpParameters = financeNPaymentFNP.retreiveFNPParameters(serviceIdList);
			String serviceID  = serviceIdList.get(0);
			if(fnpParameters !=null && fnpParameters.size()!=0){
				//FETCH FROM PARAM MAPPER ON SERVICEid
				List<FnpParamMapper> fnpMapperList = fnpParamMapperDOM.getParamMappingByServiceId(serviceID);
				if(fnpMapperList!= null && fnpMapperList.size()!=0){
					for(FNPParameterVO fParameterVO :fnpParameters){
						for(FnpParamMapper fnpParamMapper:fnpMapperList){
							if(fParameterVO.getName().equals(fnpParamMapper.getFpmParamName())){
								fParameterVO.setDisplayFlag(false);
								if(fnpParamMapper.getFpmMapping().equals(ConstantsFNP.FNP_STATIC)){
									fParameterVO.setValue(fnpParamMapper.getFpmType());
								}
								fParameterVO.setMapping(fnpParamMapper.getFpmMapping());
								
								break;
							}	
						}
					}
				}
				
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		return fnpParameters;
	}
	/**
	 * @param fnpPaymentAdviceReqVO
	 * @return FNPPaymentAdviceRspnsVO
	 * @throws FNPException
	 */
	public FNPPaymentAdviceRspnsVO generatePaymentAdvice(FNPPaymentAdviceReqVO fnpPaymentAdviceReqVO){
		return financeNPaymentFNP.generatePaymentAdvice(fnpPaymentAdviceReqVO);
	}
	/**
	 * @param clentId
	 * @return FNPAccountTypeVO
	 * @throws FNPException
	 */
	public FNPAccountTypeVO enquireDeposits(String clentId){
		return financeNPaymentFNP.enquireDeposits(clentId);
	}
	/**
	 * @param serviceCode
	 * @return List<FnpServiceMaster>
	 */
	@Transactional
	public List<FnpServiceMaster> getFnpCodeByServiceCode(String serviceCode){
		return FnpGSDOM.getFnpCodeByServiceCode(new Long(serviceCode));
	}
	/**
	 * @param appId
	 * @param userName
	 * @param visaService
	 * @return FNPPaymentAdviceRspnsVO
	 * @throws PaymentException 
	 */

//	@Transactional
//	public FNPPaymentAdviceRspnsVO generatePayment(String appId, String userName, String visaService,List<FNPParameterVO> fnpParams){
//		return FNPManager.generatePayment(appId, userName, visaService,fnpParams);
//	}

	/**
	 * @param appId
	 * @param userName
	 * @param visaService
	 * @return
	 */
	@Transactional
	public FNPPaymentAdviceRspnsVO previewPaymentAdvice(String userName, String visaService,List<FNPParameterVO> fnpParams){
		return FNPManager.previewPaymentAdvice(userName, visaService,fnpParams,null);
	}

	/**
	 * @param fnpServiceMasters
	 */
	@Transactional
	public void insertAll(List<FNPCatalogVO> fnpCatalogs, String serviceCode){
		List<FnpServiceMaster> fnpServiceMasters = new ArrayList<FnpServiceMaster>();
		fnpParamMapperDOM.deleteAll(serviceCode);
		for(FNPCatalogVO fnpCatalogVO:fnpCatalogs){
			FnpServiceMaster fnpServiceMaster = new FnpServiceMaster();
			fnpServiceMaster.setFnpCode(fnpCatalogVO.getCode());
			fnpServiceMaster.setServiceCode(new Long(serviceCode));
			fnpServiceMaster.setServiceDesc(fnpCatalogVO.getDescEng());
			fnpServiceMaster.setServiceId(fnpCatalogVO.getId());
			fnpServiceMasters.add(fnpServiceMaster);
		}
		FnpGSDOM.insertAll(fnpServiceMasters,new Long(serviceCode));
	}

	
	/* (non-Javadoc)
	 * @see ae.pcfc.cldos.online.common.facade.FnpGSFacade#getFnpCatalogVOsByServiceCode(java.lang.String)
	 */
	@Transactional
	public List<FNPCatalogVO> getFnpCatalogVOsByServiceCode(String localServiceCode){
		List<FNPCatalogVO> fnpCatalogVOs = new ArrayList<FNPCatalogVO>();
		FNPCatalogVO fnpCatalogVO = new FNPCatalogVO();
		fnpCatalogVOs.add(fnpCatalogVO);
		List<FnpServiceMaster> fnpServMasterList = getFnpCodeByServiceCode(localServiceCode);
		//List<String> fnpServiceCodeList = new ArrayList<String>();
		if(fnpServMasterList!=null && fnpServMasterList.size()!=0){
			for(FnpServiceMaster fnpServiceMaster : fnpServMasterList){
				//fnpServiceCodeList.add(fnpServiceMaster.getFnpCode());
				if(fnpServiceMaster.getServiceId()!=null){
					FNPCatalogVO fnpCatalogVO1 = new FNPCatalogVO();
					fnpCatalogVO1.setCode(fnpServiceMaster.getFnpCode());
					fnpCatalogVO1.setId(fnpServiceMaster.getServiceId());
					fnpCatalogVO1.setDescEng(fnpServiceMaster.getServiceDesc());
					fnpCatalogVO1.setDescArb(fnpServiceMaster.getServiceDesc());
					fnpCatalogVOs.add(fnpCatalogVO1);
				}
				
			}
		}
		
		
		//call fnp
		//fnpCatalogVOs.addAll(retreiveFNPCatalog(fnpServiceCodeList));
		return fnpCatalogVOs;
	}
	
	/* (non-Javadoc)
	 * @see ae.pcfc.cldos.online.common.facade.FnpGSFacade#previewPaymentInformation(ae.pcfc.cldos.online.common.vo.ep.peyment.PaymentAdviceRequestVO)
	 */
	@Transactional
	public PaymentAdviceResponseVO previewPaymentInformation(
			PaymentAdviceRequestVO paymentAdviceRequestVO) throws BadAppException,NoSuchCompanyException,GSAppException,FNPException{
		String fnpServiceId = paymentAdviceRequestVO.getFnpServiceCode();
		UserVO userVO = paymentAdviceRequestVO.getUserVO();
		User user = userDOM.findUserAndClientByUserName(userVO.getUsername());
		Client client = user.getClient();
		String licenserNo = tTscClientCompanyDOM.getLicenseNumberNyTrakheesId(client.getCTrakheesId());
		PaymentAdviceResponseVO paymentAdviceResponseVO = new PaymentAdviceResponseVO();
		String overLoadEmpCode = null;
		try{
			GSFinancialDataVO gsFinancialDataVO = gsInfoManager.retriveFinancialData(licenserNo, user.getClientId());
			paymentAdviceResponseVO.setBankGuarenteeBalance(gsFinancialDataVO.getBankGuaranteeBalance());
			if(paymentAdviceRequestVO.isOverLoadService() && (((gsFinancialDataVO.getRequiredAllowed()!=0) && (gsFinancialDataVO.getActualEmplyeesNum() >= gsFinancialDataVO.getAllowed()) && (gsFinancialDataVO.getActualEmplyeesNum() <= gsFinancialDataVO.getRequiredAllowed())))){
				overLoadEmpCode = ConstantsFNP.FNP_OVERLOAD_EMP_SERV_CODE;
			}
		}catch (WebServiceIOException e) {
			throw new GSAppException(e);
		}catch (SoapFaultClientException e) {
			throw new GSAppException(e);
		}catch(Exception e){
			throw new NoSuchCompanyException(e);
		}
		//add fnp param list here
		try{
			FNPPaymentAdviceRspnsVO fnpPaymentAdviceRspnsVO = FNPManager.previewPaymentAdvice(userVO.getUsername(), fnpServiceId, paymentAdviceRequestVO.getFnpParams(),overLoadEmpCode);
			FNPAccountTypeVO fnpAccountTypeVO = FNPManager.enquireDeposits(client.getCTrakheesId());
			paymentAdviceResponseVO.setExpiryDate(fnpPaymentAdviceRspnsVO.getExpiryDate());
			paymentAdviceResponseVO.setPrepaidAccBalance(fnpAccountTypeVO.getPrepaidAccBalance());
			paymentAdviceResponseVO.setReservedAccBalance(fnpAccountTypeVO.getReservedAccBalance());
			paymentAdviceResponseVO.setPrice(fnpPaymentAdviceRspnsVO.getPaymentAdviceAmount());
			paymentAdviceResponseVO.setNewBalance(fnpAccountTypeVO.getReservedAccBalance() - 
					fnpPaymentAdviceRspnsVO.getPaymentAdviceAmount());
			for(FNPServicePayResponseVO fNPServicePayResponseVO:fnpPaymentAdviceRspnsVO.getServicePaymntResponeList()){
				if(fNPServicePayResponseVO.getServiceId().equals(fnpServiceId)){
					paymentAdviceResponseVO.setServiceCharges(fNPServicePayResponseVO.getSeriveAmount());
				}
				if(overLoadEmpCode!= null && fNPServicePayResponseVO.getServiceId().equals(overLoadEmpCode)){
					paymentAdviceResponseVO.setOverLoadCharges(fNPServicePayResponseVO.getSeriveAmount());
				}
			}
		}catch(WebServiceIOException e){
			throw new FNPException(e);
		}
	
		return paymentAdviceResponseVO;
		
	}
	
	/**
	 * @return
	 */
	@Transactional
	public  List<FnpDefaultParamsVO> getDefaultParams(){
		List<FnpDefaultParamsVO> defparamVos = new ArrayList<FnpDefaultParamsVO>();
		List<FnpDefaultParams> fDefaultParams = fnpDefaultParamsDOM.getDefaultParams();
		if(fDefaultParams!=null && fDefaultParams.size()!=0){
			for(FnpDefaultParams fParam:fDefaultParams){
				FnpDefaultParamsVO fnpDefaultParamsVO = new FnpDefaultParamsVO();
				fnpDefaultParamsVO.setFdpCode(fParam.getFdpCode());
				fnpDefaultParamsVO.setFdpFieldName(fParam.getFdpFieldName());
				fnpDefaultParamsVO.setFdpValue(fParam.getFdpValue());
				defparamVos.add(fnpDefaultParamsVO);
			}
		}
		return defparamVos;
	}

	/**
	 * @param fnpParamMappers
	 * @param serviceIds
	 */
	@Transactional
	public void saveParamMapping(List<FnpParamMapperVO> fnpParamMappers, List<String> serviceIds){
		List<FnpParamMapper> fnpMappers = new ArrayList<FnpParamMapper>();
			for(FnpParamMapperVO fMapperVO :fnpParamMappers){
				FnpParamMapper fnParamMapper = new FnpParamMapper();
				fnParamMapper.setFpmMapping(fMapperVO.getFpmMapping());
				fnParamMapper.setFpmParamName(fMapperVO.getFpmParamName());
				fnParamMapper.setFpmServiceId(fMapperVO.getFpmServiceId());
				fnParamMapper.setFpmType(fMapperVO.getFpmType());
				fnpMappers.add(fnParamMapper);
			}
		fnpParamMapperDOM.saveParamMapping(fnpMappers, serviceIds);
	}
	/**
	 * @param clientId
	 * @param startDate
	 * @param endDate
	 * @return
	 * @throws FNPException
	 */
	@Transactional
	public List<FNPPrepaidTransactionVO> enquireDepositTransaction(String userName, Date startDate, Date endDate) {
		 return FNPManager.enquireDepositTransaction(userName, startDate, endDate);
	}

}
